#include "ring_thread_list.h"

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>

struct list
{
	thread_t thread;
	struct list *next;
	struct list *prev;
	int* size;
};


int size(struct list* list){
	return isempty(list) ? 0 : *list->size;
}


struct list* create(struct list *node,thread_t nthread){
	if(isempty(node)){
		node=(struct list *)malloc(sizeof(struct list));
		node->thread=nthread;
		node->next=node;
		node->prev=node;
		node->size=malloc(sizeof(int));
		*(node->size)=1;
	}
	return node;
}

void display(struct list *list){
	struct list* node=list;
	if(!isempty(node)) {
		fprintf(stderr,";;;;;;\nHead");
		do{
			fprintf(stderr,"{%p~id: %d}\n",node->thread,node->thread->thread_id);
			node=node->next;
		}while(!end(list,node));
		fprintf(stderr,";;;;;;\n");
	}
	else
		fprintf(stderr,"The list is empty\n");
}
int end(struct list* list,struct list* node){
	return 	node==list;
}
thread_t head(struct list* list){
	return list ? list->thread : NULL;
}
struct list* insert(struct list *node,thread_t nthread){
	struct list *new1=NULL;
	if(isempty(node)){
		return create(node,nthread);
	}
	(*node->size)++;
	new1=create(new1,nthread);
	new1->prev=node->prev;
	node->prev->next=new1;
	node->prev=new1;
	new1->next=node;
	free(new1->size);
	new1->size=node->size;
	return node;
}
int isempty(struct list* list){
	return NULL==list;
}
struct list* remove_element(struct list* list,thread_t thread){
	struct list* node=list;
	if(!isempty(node)) {
		do{
			if(thread==node->thread){
				if(size(list)==1){
					free(list->size);
					free(list);
					return NULL;
				}
				node->prev->next=node->next;
				node->next->prev=node->prev;
				list=list->next;
				(*list->size)--;//display(list);
				free(node);
				break;
			}
			node=node->next;
		}while(!end(list,node));
	}
	//		fprintf(stderr,"The list is empty\n");
	return list;
}
struct thread* in(struct list* list,thread_t thread){
	struct list* node=list;
	if(!isempty(node)) {
		do{
			if(thread==node->thread){
				return node;
			}
			node=node->next;
		}while(!end(list,node));
		return NULL;
	}
	else
		//		fprintf(stderr,"The list is empty\n");
		return NULL;
}

struct list* move_all(struct list* srclist,struct list* destlist){
	/*TODO il suffit de lier le premier
	 *  element de la runq au dernier
	 *  de la waitings et de lier la size
	 */
	struct list* node=srclist;
	if(!isempty(node)) {
		do{
			node->thread->status=RUNNING;
			destlist=insert(destlist,node->thread);
			node=node->next;
			srclist=remove_element(srclist,node->thread);
		}
		while(!isempty(srclist));
	}
	return destlist;
}
struct list* free_list(struct list* list){
	struct list* node=list;
	if(!isempty(node)) {
		if(list->size){
			free(list->size);
			list->size=NULL;}
		do{
			if(NULL!=node->thread){
				node->thread=delete_thread(node->thread);
			}
			struct list* tmp=node;
			node=node->next;
			if(NULL!=tmp){
				free(tmp);
				tmp=NULL;
			}
		}while(!end(list,node));
	}

	return NULL;
}
struct list* shift(struct list* list){
	if(list)
		list=list->prev;
	return list;
}
